{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Flask基础"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 0. 在github或码云上创建代码仓库"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 1. 在PyCharm中构建虚拟环境\n",
    "### 1.1 在Windows资源管理器中创建项目文件夹（如果有代码仓库，则使用git clone命令克隆仓库并创建项目文件夹）\n",
    "### 1.2 使用Windows注册表编辑器在右键菜单添加Open Folder With PyCharm\n",
    "### 1.3 为项目设置解释器（构建虚拟环境，选择Pthon3.9作为base interpreter\n",
    "### 1.4 创建requirements.txt文件\n",
    "### 1.5 在虚拟环境的终端中使用pip install -r requrements.txt -i httfps://pypi.tuna.tsinghua.edu.cn/simple 命令安装所有项目依赖的软件包\n",
    "### 1.6 创建README.md文件"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2. 创建第一个Flask项目\n",
    "* 创建一个Flask临时项目名字不关键\n",
    "* 将其中的static和templates文件夹以及app.py文件拷贝进自己的项目（和代码仓库关联）\n",
    "* 删除Flask临时项目及磁盘文件夹\n",
    "* <h4 style=\"color:red\">在Edit configurations对话框种删除原有的Python模板并新建FlaskServer模板</h4>\n",
    "### 2.1 编写/运行app.py文件"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import datetime\n",
    "\n",
    "from flask import Flask\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-25T15:52:04.174814Z",
     "end_time": "2023-10-25T15:52:22.761462Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.2 在浏览器上url中输入： localhost:5000"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 3. debug、host和port的配置\n",
    "\n",
    "### 3.1. debug模式：\n",
    "### 在pycharm项目种设置，在jupyter种无法实现\n",
    "\n",
    "### 3.2. 修改host:\n",
    "### 修改host是为了让网络中的其它电脑能访问这个Flask项目驱动的页面\n",
    "### 在additional options中 填入：--host=0.0.0.0\n",
    "\n",
    "### 3.3. 修改端口号port:\n",
    "### 在additional options中 填入：--port=8000"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4. URL与视图\n",
    "### 4.1 url\n",
    "#### http[80]/https[443]://www.baidu.com:port/path"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/1')\n",
    "def register():\n",
    "    return \"这是网站的注册页面\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-25T16:41:12.516111Z",
     "end_time": "2023-10-25T16:43:13.019250Z"
    },
    "pycharm": {
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 4.2 url带参数——GET请求\n",
    "#### 4.2.1 http[80]/https[443]://www.baidu.com:port/path/<leixing:参数>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-25T20:14:34.776559Z",
     "end_time": "2023-10-25T20:18:16.847607Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 4.2.2 http[80]/https[443]://www.baidu.com:port/path/?参数1=1&参数2=abc"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-25T20:28:51.012676Z",
     "end_time": "2023-10-25T20:50:51.121814Z"
    },
    "pycharm": {
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4.3 通过POST请求发送参数"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list', methods=['POST','GET'])\n",
    "def book_list():\n",
    "    if request.method == 'GET':\n",
    "        page = request.args.get('page', default=1, type=int)\n",
    "        name = request.args.get('name', default='', type=str)\n",
    "        return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "    else:\n",
    "        print('POST')\n",
    "        data = request.get_data().decode('utf-8')\n",
    "        print(data)\n",
    "        data1 = json.loads(data)\n",
    "        print(type(data1))  # <class 'dict'>\n",
    "        print(data1)  # {'id': 1, 'name': 'Alice'}\n",
    "        return 'POST'\n",
    "\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 响应POST请求的三个’坑‘：\n",
    "1. json改名的'坑'：在Python 3.10.1之后的版本,json改名叫simplejson了。所以要使用pip install simplejson\n",
    "2. json默认使用的是严谨格式的'坑'：如果前端发到后端的字典中使用单引号，由于json默认使用严谨格式，所以json.loads()方法会报错——’json.decoder.JSONDecodeError: Invalid control character at: line 2 column 18 (char 19)‘。解决方法就是把单引号改为双引号。\n",
    "3. json.dumps(data)将汉字转换为unicode编码的坑。原因：json默认会进行字符转换。解决方法： 添加 ensure_ascii 参数——》json.dumps(data, ensure_ascii=False)"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 5. Jinja2模板渲染\n",
    "### 5.1 直接加载html模板"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T12:01:48.717047Z",
     "end_time": "2023-10-26T12:04:52.520645Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.2 带参数加载html模板"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T12:09:29.214045Z",
     "end_time": "2023-10-26T12:10:06.090886Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.3 模板使用对象属性\n",
    "#### 5.3.1 类对象"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = User(username='张三', gender='男', email='abced@tju.edu.cn')\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "class User(object):\n",
    "    def __init__(self, username, gender, email):\n",
    "        self.username = username\n",
    "        self.gender = gender\n",
    "        self.email = email\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T12:23:12.267165Z",
     "end_time": "2023-10-26T12:25:39.006080Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 5.3.2 字典对象"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T12:33:55.758579Z",
     "end_time": "2023-10-26T12:42:12.793573Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.4 过滤器的使用\n",
    "#### 5.4.1 Jinjia2自带过滤器：length, 其它自带过滤器30多个，用法可以自己查手册"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T12:46:56.069676Z",
     "end_time": "2023-10-26T12:50:48.708947Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 5.4.2 自定义过滤器"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask, request, render_template\n",
    "import datetime\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "def datetime_format(value, format=\"%Y-%m-%d %H:%M\"):\n",
    "    return value.strftime(format)\n",
    "\n",
    "\n",
    "app.add_template_filter(datetime_format, 'dformat')  # dformat是自定义过滤器的名字\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/myfilter')\n",
    "def myfilter():\n",
    "    theTime = datetime.datetime.today()\n",
    "    print(theTime)\n",
    "    return render_template('myfilter.html', time=theTime)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-30T15:16:42.707518Z",
     "end_time": "2023-10-30T15:16:47.316460Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.5 控制语句\n",
    "### 5.5.1 if语句"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [26/Oct/2023 17:46:53] \"GET /control HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [26/Oct/2023 17:46:54] \"GET /control HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask, request, render_template\n",
    "import datetime\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "def datetime_format(value, format=\"%Y-%m-%d %H:%M\"):\n",
    "    return value.strftime(format)\n",
    "\n",
    "\n",
    "app.add_template_filter(datetime_format, 'dformat')  # dformat是自定义过滤器的名字\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/myfilter')\n",
    "def myfilter():\n",
    "    theTime = datetime.datetime.today()\n",
    "    print(theTime)\n",
    "    return render_template('myfilter.html', time=theTime)\n",
    "\n",
    "\n",
    "@app.route('/control')\n",
    "def control():\n",
    "    return render_template('control.html', age=17)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T17:46:50.433197Z",
     "end_time": "2023-10-26T17:47:48.091580Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.5.2 for循环语句"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [26/Oct/2023 17:51:38] \"GET / HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [26/Oct/2023 17:51:43] \"GET /namelist HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask, request, render_template\n",
    "import datetime\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "def datetime_format(value, format=\"%Y-%m-%d %H:%M\"):\n",
    "    return value.strftime(format)\n",
    "\n",
    "\n",
    "app.add_template_filter(datetime_format, 'dformat')  # dformat是自定义过滤器的名字\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/myfilter')\n",
    "def myfilter():\n",
    "    theTime = datetime.datetime.today()\n",
    "    print(theTime)\n",
    "    return render_template('myfilter.html', time=theTime)\n",
    "\n",
    "\n",
    "@app.route('/control')\n",
    "def control():\n",
    "    return render_template('control.html', age=17)\n",
    "\n",
    "\n",
    "@app.route('/namelist')\n",
    "def namelist():\n",
    "    namelist = ['张三', '李四', '王五', '陈六']\n",
    "    return render_template('namelist.html', namelist=namelist)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.6 模板继承"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [26/Oct/2023 20:05:05] \"GET / HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [26/Oct/2023 20:05:11] \"GET /child1 HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask, request, render_template\n",
    "import datetime\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "def datetime_format(value, format=\"%Y-%m-%d %H:%M\"):\n",
    "    return value.strftime(format)\n",
    "\n",
    "\n",
    "app.add_template_filter(datetime_format, 'dformat')  # dformat是自定义过滤器的名字\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/myfilter')\n",
    "def myfilter():\n",
    "    theTime = datetime.datetime.today()\n",
    "    print(theTime)\n",
    "    return render_template('myfilter.html', time=theTime)\n",
    "\n",
    "\n",
    "@app.route('/control')\n",
    "def control():\n",
    "    return render_template('control.html', age=17)\n",
    "\n",
    "\n",
    "@app.route('/namelist')\n",
    "def namelist():\n",
    "    namelist = ['张三', '李四', '王五', '陈六']\n",
    "    return render_template('namelist.html', namelist=namelist)\n",
    "\n",
    "\n",
    "@app.route('/child1')\n",
    "def child1():\n",
    "    return render_template('child1.html')\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-26T20:05:04.060552Z",
     "end_time": "2023-10-26T20:08:43.540872Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.7 加载静态文件\n",
    "#### 5.7.1 加载图片"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [29/Oct/2023 11:01:20] \"GET / HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [29/Oct/2023 11:01:26] \"GET /clock HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [29/Oct/2023 11:01:26] \"GET /css/style.css HTTP/1.1\" 404 -\n",
      "127.0.0.1 - - [29/Oct/2023 11:01:26] \"GET /js/jquery.min.js HTTP/1.1\" 404 -\n",
      "127.0.0.1 - - [29/Oct/2023 11:01:26] \"GET /js/index.js HTTP/1.1\" 404 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask, request, render_template\n",
    "import datetime\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "\n",
    "\n",
    "def datetime_format(value, format=\"%Y-%m-%d %H:%M\"):\n",
    "    return value.strftime(format)\n",
    "\n",
    "\n",
    "app.add_template_filter(datetime_format, 'dformat')  # dformat是自定义过滤器的名字\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return render_template('index.html')\n",
    "\n",
    "\n",
    "@app.route('/login')\n",
    "def login():\n",
    "    return '这是网站的登录页面'\n",
    "\n",
    "\n",
    "@app.route('/register/<int:id>')\n",
    "def register(id):\n",
    "    return f\"你的id是{id}\"\n",
    "\n",
    "\n",
    "@app.route('/book/list')\n",
    "def book_list():\n",
    "    page = request.args.get('page', default=1, type=int)\n",
    "    name = request.args.get('name', default='', type=str)\n",
    "    return f\"您获取的是第{page}的图书列表,作者是{name}\"\n",
    "\n",
    "\n",
    "@app.route('/blog/<blog_id>')\n",
    "def blog(blog_id):\n",
    "    return render_template('blog.html', blog_id=blog_id)\n",
    "\n",
    "\n",
    "@app.route('/user')\n",
    "def user():\n",
    "    user = {'username': '张三', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('user.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/filter')\n",
    "def filter():\n",
    "    user = {'username': '张三xxxxxx', 'gender': '男', 'email': 'abcde@tju.edu.cn'}\n",
    "    return render_template('filter.html', user=user)\n",
    "\n",
    "\n",
    "@app.route('/myfilter')\n",
    "def myfilter():\n",
    "    theTime = datetime.datetime.today()\n",
    "    print(theTime)\n",
    "    return render_template('myfilter.html', time=theTime)\n",
    "\n",
    "\n",
    "@app.route('/control')\n",
    "def control():\n",
    "    return render_template('control.html', age=17)\n",
    "\n",
    "\n",
    "@app.route('/namelist')\n",
    "def namelist():\n",
    "    namelist = ['张三', '李四', '王五', '陈六']\n",
    "    return render_template('namelist.html', namelist=namelist)\n",
    "\n",
    "\n",
    "@app.route('/child1')\n",
    "def child1():\n",
    "    return render_template('child1.html')\n",
    "\n",
    "\n",
    "@app.route('/image')\n",
    "def image():\n",
    "    return render_template('image.html')\n",
    "\n",
    "\n",
    "@app.route('/image2')\n",
    "def image2():\n",
    "    return render_template('image2.html', filename='img/2.jpg')\n",
    "\n",
    "\n",
    "@app.route('/clock')\n",
    "def clock():\n",
    "    return render_template('./clock/index.html')\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T10:27:48.585001Z",
     "end_time": "2023-10-29T10:32:20.588614Z"
    },
    "pycharm": {
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 5.7.2 加载css文件"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 6. Flask使用MySQL数据库\n",
    "### 6.1 安装软件包"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "raw",
   "source": [
    "pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple\n",
    "pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple\n",
    "pip install wsgi -i https://pypi.tuna.tsinghua.edu.cn/simple"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 6.2 Flask链接MySQL数据库"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1,)\n",
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "with app.app_context():\n",
    "    with db.engine.connect() as conn:\n",
    "        rs = conn.execute(text(\"select 1\"))\n",
    "        print(rs.fetchone())\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T20:59:45.791506Z",
     "end_time": "2023-10-29T20:59:52.972854Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 6.3 ORM模型与表映射"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表，只能在没有表的时候，创建信标，不能更改表结构，所以正式使用的时候很少用\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T21:00:05.557295Z",
     "end_time": "2023-10-29T21:01:35.701603Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 6.4 ORM模型的CRUD操作：增删改查\n",
    "#### 6.4.1 Create操作"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [29/Oct/2023 21:06:14] \"GET / HTTP/1.1\" 200 -\n",
      "127.0.0.1 - - [29/Oct/2023 21:06:32] \"GET /user/add HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T21:06:04.977136Z",
     "end_time": "2023-10-29T21:07:17.882026Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 6.4.2 查找操作"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "C:\\Users\\slyb\\AppData\\Local\\Temp\\ipykernel_5648\\939110176.py:41: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)\n",
      "  user = User.query.get(1)  #根据主键查找\n",
      "127.0.0.1 - - [29/Oct/2023 21:13:33] \"GET /user/query HTTP/1.1\" 200 -\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 张三 123456\n",
      "1 张三 123456\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T21:13:25.117828Z",
     "end_time": "2023-10-29T21:13:55.051317Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 6.4.3 Update改操作"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [29/Oct/2023 21:20:52] \"GET /user/update HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/update')\n",
    "def update_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    user.password = '654321'\n",
    "    db.session.commit()\n",
    "    return \"数据修改成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T21:20:45.175260Z",
     "end_time": "2023-10-29T21:21:06.512849Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 6.4.3 Delete删除操作"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "127.0.0.1 - - [29/Oct/2023 21:24:02] \"GET /user/delete HTTP/1.1\" 200 -\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/update')\n",
    "def update_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    user.password = '654321'\n",
    "    db.session.commit()\n",
    "    return \"数据修改成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/delete')\n",
    "def delete_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    db.session.delete(user)\n",
    "    db.session.commit()\n",
    "    return \"数据删除成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-29T21:23:58.632561Z",
     "end_time": "2023-10-29T21:25:25.781311Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 6.5 ORM模型外键与表关系\n",
    "#### 6.5.1 方法一："
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n",
      "C:\\Users\\slyb\\AppData\\Local\\Temp\\ipykernel_5200\\3308383537.py:57: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)\n",
      "  user = User.query.get(1)  #根据主键查找\n",
      "[2023-10-30 14:14:40,474] ERROR in app: Exception on /user/query [GET]\n",
      "Traceback (most recent call last):\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask\\app.py\", line 1455, in wsgi_app\n",
      "    response = self.full_dispatch_request()\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask\\app.py\", line 869, in full_dispatch_request\n",
      "    rv = self.handle_user_exception(e)\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask\\app.py\", line 867, in full_dispatch_request\n",
      "    rv = self.dispatch_request()\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask\\app.py\", line 852, in dispatch_request\n",
      "    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)\n",
      "  File \"C:\\Users\\slyb\\AppData\\Local\\Temp\\ipykernel_5200\\3308383537.py\", line 57, in query_user\n",
      "    user = User.query.get(1)  #根据主键查找\n",
      "  File \"<string>\", line 2, in get\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\util\\deprecations.py\", line 386, in warned\n",
      "    return fn(*args, **kwargs)  # type: ignore[no-any-return]\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\query.py\", line 1136, in get\n",
      "    return self._get_impl(ident, loading.load_on_pk_identity)\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\query.py\", line 1145, in _get_impl\n",
      "    return self.session._get_impl(\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\session.py\", line 3831, in _get_impl\n",
      "    return db_load_fn(\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\loading.py\", line 690, in load_on_pk_identity\n",
      "    session.execute(\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\session.py\", line 2306, in execute\n",
      "    return self._execute_internal(\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\sqlalchemy\\orm\\session.py\", line 2176, in _execute_internal\n",
      "    bind = self.get_bind(**bind_arguments)\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask_sqlalchemy\\session.py\", line 53, in get_bind\n",
      "    engines = self._db.engines\n",
      "  File \"F:\\temp\\FlaskDemo\\venv\\lib\\site-packages\\flask_sqlalchemy\\extension.py\", line 690, in engines\n",
      "    raise RuntimeError(\n",
      "RuntimeError: The current Flask app is not registered with this 'SQLAlchemy' instance. Did you forget to call 'init_app', or did you create multiple 'SQLAlchemy' instances?\n",
      "127.0.0.1 - - [30/Oct/2023 14:14:40] \"GET /user/query HTTP/1.1\" 500 -\n",
      "127.0.0.1 - - [30/Oct/2023 14:14:43] \"GET /user/query HTTP/1.1\" 200 -\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 张三 123456\n",
      "1 张三 123456\n",
      "Flask基础\n",
      "Django基础教程\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "    articles = db.relationship('Article', back_populates=\"authors\")  #这个需要两边的类双向绑定,在这个User表单中需要生成一个名为authors辅助对象\n",
    "\n",
    "\n",
    "class Article(db.Model):\n",
    "    __tablename__ = 'article'\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    title = db.Column(db.String(200), nullable=False)\n",
    "    content = db.Column(db.Text, nullable=False)\n",
    "    # 添加作者的外键\n",
    "    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))  # 这个是子表，在子表里创建外键，外键要与父表中的主键相关联，这里的user是表单名__tablename__\n",
    "    authors = db.relationship('User', back_populates=\"articles\")  #这个需要两边的类双向绑定，在这个Aritcle表单中需要生成一个名为articles的辅助对象\n",
    "    # author = db.relationship('User', backref='articles')\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user1 = User(username='张三', password='123456')\n",
    "    user2 = User(username='李四', password='123456')\n",
    "    db.session.add_all([user1, user2])\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "        for article in user.articles:\n",
    "            print(article.title)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/update')\n",
    "def update_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    user.password = '654321'\n",
    "    db.session.commit()\n",
    "    return \"数据修改成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/delete')\n",
    "def delete_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    db.session.delete(user)\n",
    "    db.session.commit()\n",
    "    return \"数据删除成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/add')\n",
    "def add_article():\n",
    "    article1 = Article(title='Flask基础', content='Flask是一个轻便但功能强大的Web框架')\n",
    "    article1.author = User.query.get(1)\n",
    "    article2 = Article(title='Django基础教程', content='Django是一个重量级且功能强大的Web框架')\n",
    "    article2.author = User.query.get(1)\n",
    "    article3 = Article(title='Python基础教程', content='Python是一门功能强大的计算机编程语言')\n",
    "    article3.author = User.query.get(2)\n",
    "\n",
    "    db.session.add_all([article1, article2, article3])\n",
    "    db.session.commit()\n",
    "    return \"文章创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/query')\n",
    "def query_article():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    # users = User.query.filter_by(username='张三')\n",
    "    for article in user.articles:\n",
    "        print(article.title)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-30T14:14:36.487668Z",
     "end_time": "2023-10-30T14:18:20.129796Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 6.5.2 方法二："
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "class Article(db.Model):\n",
    "    __tablename__ = 'article'\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    title = db.Column(db.String(200), nullable=False)\n",
    "    content = db.Column(db.Text, nullable=False)\n",
    "    # 添加作者的外键\n",
    "    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))\n",
    "    # author = db.relationship('User', back_populates=\"articles\") 这个需要两边的类双向绑定\n",
    "    author = db.relationship('User', backref='articles')\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "with app.app_context():\n",
    "    db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/update')\n",
    "def update_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    user.password = '654321'\n",
    "    db.session.commit()\n",
    "    return \"数据修改成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/delete')\n",
    "def delete_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    db.session.delete(user)\n",
    "    db.session.commit()\n",
    "    return \"数据删除成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/add')\n",
    "def add_article():\n",
    "    article = Article(title='Flask基础', content='Flask是一个轻便但功能强大的Web框架')\n",
    "    article.author = User.query.get(1)\n",
    "    db.session.add(article)\n",
    "    db.session.commit()\n",
    "    return \"文章创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/query')\n",
    "def query_article():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for article in user.articles:\n",
    "        print(article.title)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-30T11:57:38.283048Z",
     "end_time": "2023-10-30T11:58:12.576399Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 6.6 Flask migrate迁移ORM模型\n",
    "#### pip install flask-migrate -i https://pypi.tuna.tsinghua.edu.cn/simple"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " * Serving Flask app '__main__'\n",
      " * Debug mode: off\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n",
      " * Running on http://127.0.0.1:5000\n",
      "Press CTRL+C to quit\n"
     ]
    }
   ],
   "source": [
    "from flask import Flask\n",
    "from flask_sqlalchemy import SQLAlchemy\n",
    "from sqlalchemy import text\n",
    "from flask_migrate import Migrate\n",
    "\n",
    "# 使用Flask类创建一个app对象\n",
    "app = Flask(__name__)\n",
    "HOSTNAME = '127.0.0.1'\n",
    "PORT = 3306\n",
    "USERNAME = 'root'\n",
    "PASSWORD = ''\n",
    "DATABASE = 'flask_test'\n",
    "app.config[\n",
    "    'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'\n",
    "db = SQLAlchemy(app)\n",
    "migrate = Migrate(app, db)\n",
    "# ORM模型映射三步曲：在notebook中不能用，要在app.py中编写代码并运行后才可操作\n",
    "# 1. 在终端中执行命令：flask db init  这步只需要执行一次，会在磁盘文件夹下生成一个migrations的文件夹\n",
    "# 2. 在终端中执行命令：flask db migrate 识别ORM模型的改变，生成迁移脚本\n",
    "# 3. 在终端中执行命令：flask db upgrade 运行迁移脚本，将各种表结构的变化同步到数据库中\n",
    "\n",
    "class User(db.Model):\n",
    "    __tablename__ = \"user\"\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    username = db.Column(db.String(100), nullable=False)\n",
    "    password = db.Column(db.String(100), nullable=False)\n",
    "\n",
    "\n",
    "class Article(db.Model):\n",
    "    __tablename__ = 'article'\n",
    "    id = db.Column(db.Integer, primary_key=True, autoincrement=True)\n",
    "    title = db.Column(db.String(200), nullable=False)\n",
    "    content = db.Column(db.Text, nullable=False)\n",
    "    # 添加作者的外键\n",
    "    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))\n",
    "    # author = db.relationship('User', back_populates=\"articles\") 这个需要两边的类双向绑定\n",
    "    author = db.relationship('User', backref='articles')\n",
    "\n",
    "\n",
    "# user = User(username=\"张三\",password='123456')\n",
    "# with app.app_context():\n",
    "#     db.create_all()  #创建表\n",
    "\n",
    "\n",
    "# 创建一个路由和视图函数的映射，'/'代表跟路由\n",
    "@app.route('/')\n",
    "def hello_world():  # put application's code here\n",
    "    return 'Hello World!'\n",
    "\n",
    "\n",
    "@app.route('/user/add')\n",
    "def add_user():\n",
    "    user = User(username='张三', password='123456')\n",
    "    db.session.add(user)\n",
    "    db.session.commit()\n",
    "    return \"用户创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/query')\n",
    "def query_user():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    print(user.id, user.username, user.password)\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for user in users:\n",
    "        print(user.id, user.username, user.password)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/update')\n",
    "def update_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    user.password = '654321'\n",
    "    db.session.commit()\n",
    "    return \"数据修改成功\"\n",
    "\n",
    "\n",
    "@app.route('/user/delete')\n",
    "def delete_user():\n",
    "    user = User.query.filter_by(username='张三').first()\n",
    "    db.session.delete(user)\n",
    "    db.session.commit()\n",
    "    return \"数据删除成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/add')\n",
    "def add_article():\n",
    "    article = Article(title='Flask基础', content='Flask是一个轻便但功能强大的Web框架')\n",
    "    article.author = User.query.get(1)\n",
    "    db.session.add(article)\n",
    "    db.session.commit()\n",
    "    return \"文章创建成功\"\n",
    "\n",
    "\n",
    "@app.route('/article/query')\n",
    "def query_article():\n",
    "    user = User.query.get(1)  #根据主键查找\n",
    "    users = User.query.filter_by(username='张三')\n",
    "    for article in user.articles:\n",
    "        print(article.title)\n",
    "    return \"数据查找成功\"\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    app.run()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-10-30T15:16:54.970330Z",
     "end_time": "2023-10-30T15:20:45.005125Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 7. 利用Pycharm对项目进行远程部署"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
